#ifndef __OS_PORT_H__
#define __OS_PORT_H__

#define OS_PORT_MAX_TCP_QUEUE 10
#define OS_PORT_MAX_FILE_PATH 1024

#ifdef WIN32
  #define OSP_SOCKET_EAGAIN 11
  #define OSP_SOCKET_ETIMEDOUT 10060
  #define OSP_SOCKET_EWOULDBLOCK 10035

  #define OSP_SOCKET_EINTR 4
  #define OSP_SOCKET_WSAEINVAL 10022
#else /* WIN32 */
  #define OSP_SOCKET_EAGAIN 11
  #define OSP_SOCKET_ETIMEDOUT 62
  #define OSP_SOCKET_EWOULDBLOCK OSP_SOCKET_EAGAIN

  #define OSP_SOCKET_EINTR 4
  #define OSP_SOCKET_WSAEINVAL 10022
#endif /* WIN32 */

/* DWORD (thread id) is used for sys_thread_t but we won't include windows.h */
typedef void* osp_thread_t;

/** Function prototype for thread functions */
typedef uint32 (*fp_thread_t)(void *arg);

#define OSP_EVENT_READ         0x01
#define OSP_EVENT_WRITE        0x02

#ifdef WIN32
int gettimeofday(struct timeval *tp, void *tzp);
#endif /* WIN32 */

/* If the string is valid, 
 * the string is converted to the IPV4 address of the 32 bit binary network byte order*/
uint32 osp_inet_addr(uint08 *addr);

/*Obtain IP address with domain name or host name*/
sint32 osp_gethostbyname(sint08 *domain_name,sint08 *ipaddr);

/* get local IP and local port */
sint32 osp_getsockname(uint32 sockfd,uint08 *localaddr,uint16 *lport);

/* get peer IP and local port */
sint32 osp_getpeername(uint32 sockfd,uint08 *peeraddr,uint16 *pport);

uint32 osp_time_tickget();

void osp_timer_f_sleep(unsigned long unMilliSeconds);

/* initialize a windows socket */
sint32 osp_socket_f_init(void);

/* uninitialize a windows socket */
sint32 osp_socket_f_uninit(void);

/*
 * initialize a socket
 *
 * @param: none
 *
 * return: sockfd, a socket description
 */
uint32 osp_socket_f_open(int af, int type, int protocol);

/*
 * bind socket with address-port
 *
 * @param: none
 *
 * return: sockfd, a socket description
 */
sint32 osp_socket_f_bind(uint32 sockfd, uint08 * lipaddr, uint16 uport);

/*
 * connect to dest-server
 *
 * @param: sockfd, a socket description
 * @param: ipaddr, the IP of remote host
 * @param: uport, the port of remote host 
 *
 * return: 1, success; 0, fail
 */
sint32 osp_socket_f_connect(uint32 sockfd, char * ipaddr, uint16 uport);

/*
 * socket ioctl
 *
 * @param: sockfd, a socket description
 * @param: i_flag_nonblock, nonblock or not
 *
 * return: 1, success; else, fail
 */
sint32 osp_socket_f_nonblock(uint32 sockfd, sint32 i_flag_nonblock);

/*
 * socket ioctl
 *
 * @param: sockfd, a socket description
 * @param: i_nb_available
 *
 * return: 1, success; else, fail
 */
sint32 osp_socket_f_getavailable(uint32 sockfd);

/*
 * listen on a port
 *
 * @param: sockfd, a socket description
 * @param: backlog, length of waiting queue
 *
 * return: 1, success; 0, fail
 */
sint32 osp_socket_f_listen(uint32 sockfd, uint16 backlog);

/*
 * check tcp client status
 *
 * @param: sockfd, a socket description
 *
 * return:NULL, a socket description
 */
void osp_socket_f_keepalive(uint32 sockfd);

/*
 * waiting and receiving connect-request from remote host
 *
 * @param: lis_sockfd, a socket description
 *
 * return: apt_sockfd, a socket description
 */
sint32 osp_socket_f_accept(sint32 lis_sockfd);

/*
 * waiting and receiving connect-request from remote host
 *
 * @param: lis_sockfd, a socket description
 *
 * return: apt_sockfd, a socket description
 */

sint32 sgcc_socket_f_accept(sint32 lis_sockfd,uint08 * lis_addr,uint16 * lis_port);

/*
 * receive data by socket
 *
 * @param: sockfd, a socket description
 * @param: up_buff, a buffer for saving data 
 * @param: buff_size, max length of data that can be received
 *
 * return: the length of data has been received
 */
sint32 osp_socket_f_read(uint32 sockfd, uint08 * up_buff, sint32 buff_size);

/*
 * receive data by socket
 *
 * @param: sockfd, a socket description
 * @param: up_buff, a buffer for saving data 
 * @param: buff_size, max length of data that can be received
 *
 * return: the length of data has been received
 */
sint32 osp_socket_f_readfrom(uint32 sockfd, uint08 * up_buff, sint32 buff_size);

/*
 * send data by socket
 *
 * @param: sockfd, a socket description
 * @param: up_buff, point to the header of data 
 * @param: len, length of data that will be sent
 *
 * return: the length of data has been sent
 */
sint32 osp_socket_f_write(uint32 sockfd, uint08 * up_buff, sint32 len);

/*
 * send data by socket
 *
 * @param: sockfd, a socket description
 * @param: up_buff, point to the header of data 
 * @param: len, length of data that will be sent
 *
 * return: the length of data has been sent
 */
sint32 osp_socket_f_writeto(uint32 sockfd, uint08 * up_buff, sint32 len,void * addr_to, uint16 port_to);

sint32 osp_socket_f_select(uint32 sockfd, sint32 event, sint32 i_nb_secs);

/*
 * close connection
 *
 * @param: sockfd, a socket description
 *
 * return: none
 */
void osp_socket_f_close(uint32 sockfd);

sint32 osp_socket_f_geterror(void);

/*
 * open a file and return file description
 *
 * @param: u_rel_directory, relative directory
 * @param: u_file_name, file-name of the specified file
 *
 * return: fp_open, file description.
 */
FILE * osp_file_f_fopen(uint08 * p_rel_directory, uint08 * p_file_name, uint08 * p_open_mode);

sint32 osp_thread_f_open(fp_thread_t fp_thread_entry, void *arg, void *pthreadid);

sint32 osp_thread_f_close(void *pthread);

#endif /* __OS_PORT_H__ */

